﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace CompactMapper.Orm.Extensions
{
    internal static class EnumerableExtensions
    {
        /// <summary>
        /// Determines whether an IEnumerable contains any item
        /// </summary>
        /// <param name="enumerable">the IEnumerable</param>
        /// <returns>false if enumerable is null or contains no items</returns>
        public static Boolean HasItems(this IEnumerable enumerable)
        {
            var hasItems = false;
            if (enumerable != null)
            {
                IEnumerator enumerator;
                try
                {
                    enumerator = enumerable.GetEnumerator();
                    if (enumerator != null && enumerator.MoveNext())
                    {
                        hasItems = true;
                    }
                }
                catch
                {
                }
            }
            return hasItems;
        }

        /// <summary>
        /// Determines whether an IEnumerable contains no items
        /// </summary>
        /// <param name="enumerable">the IEnumerable</param>
        /// <returns>true if enumerable is null or contains no items</returns>
        public static Boolean HasNoItems(this IEnumerable enumerable)
        {
            return enumerable.HasItems() == false;
        }

        /// <summary>
        /// Enumerates over an IEnumerable
        /// This is targeted to linq queries, providing a way to execute the query without calling ToList or ToArray
        /// </summary>
        /// <param name="enumerable">the IEnumerable to enumerate</param>
        public static void Enumerate<T>(this IEnumerable<T> enumerable)
        {
            if (enumerable == null) return;
            var enumerator = enumerable.GetEnumerator();
            while (enumerator.MoveNext())
            {
            }
        }

        /// <summary>
        /// Enumerates over the collection removing nulls
        /// </summary>
        public static IEnumerable<T> ExpungeNulls<T>(this IEnumerable<T> enumerable)
        {
            if (enumerable.HasItems())
            {
                return enumerable.Where(item => !Equals(item, default(T))).AsEnumerable();
            }
            return enumerable;
        }

        /// <summary>
        /// Applies the action to each element in the list.
        /// </summary>
        /// <typeparam name="T">The enumerable item's type.</typeparam>
        /// <param name="enumerable">The elements to enumerate.</param>
        /// <param name="action">The action to apply to each item in the list.</param>
        public static void Apply<T>(this IEnumerable<T> enumerable, Action<T> action)
        {
            foreach (var item in enumerable)
                action(item);
        }

        public static IList<T> Sort<T>(this IEnumerable<T> enumerable)
        {
            var sorted = enumerable.ToList();
            sorted.Sort();
            return sorted;
        }

        public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> enumerable)
        {
            if (enumerable.HasItems())
                return enumerable;
            return Enumerable.Empty<T>();
        }
    }
}